import React, { Component } from 'react';
import { Map } from 'react-amap';
import DataSet, { DataView } from '@antv/data-set';
import { Chart, Geom, Label, Guide } from 'bizcharts';

const { Text } = Guide;

class UIMap extends Component {
  constructor(props) {
    super(props);
    this.state = {
      width: 200,
      height: 200,
      name: '',
      dv: new DataView(),
    };
    // 创建一个实例
    if (!window.districtExplorer) {
      window.AMapUI.loadUI(['geo/DistrictExplorer'], DistrictExplorer => {
        window.districtExplorer = new DistrictExplorer();
        this.switch2AreaNode(props.areaNumber);
      });
    } else {
      this.switch2AreaNode(props.areaNumber);
    }
  }

  componentWillReceiveProps(nextProps) {
    const { areaNumber } = this.props;
    if (nextProps.areaNumber && nextProps.areaNumber !== areaNumber) {
      this.switch2AreaNode(nextProps.areaNumber);
    }
  }

  // 切换区域
  switch2AreaNode = (adcode, callback) => {
    const { currentAreaNode } = this.state;
    if (currentAreaNode && `${currentAreaNode.getAdcode()}` === `${adcode}`) {
      return;
    }
    this.loadAreaNode(adcode, (error, areaNode) => {
      if (error) {
        if (callback) {
          callback(error);
        }
        return;
      }
      this.setState({ currentAreaNode: areaNode });
      if (callback) {
        callback(null, areaNode);
      }
    });
  };

  // 加载区域
  loadAreaNode = (adcode, callback) => {
    if (window.districtExplorer === undefined) return;
    window.districtExplorer.loadAreaNode(adcode, (error, areaNode) => {
      if (error) {
        if (callback) {
          callback(error);
        }
        return;
      }
      this.renderG2Map(areaNode); // 使用 G2 绘制地图

      if (callback) {
        callback(null, areaNode);
      }
    });
  };

  // 开始使用 G2 绘制地图
  renderG2Map = areaNode => {
    const adcode = areaNode.getAdcode();
    const geoJSON = areaNode.getSubFeatures(); // 获取 geoJSON 数据
    const name = areaNode.getName();
    const { currentAreaNode } = this.state;
    if (!geoJSON || (currentAreaNode && `${currentAreaNode.getAdcode()}` === `${adcode}`)) {
      return;
    }
    const dv = this.processData(geoJSON);
    const { width: propsWidth } = this.props;
    // start: 计算地图的最佳宽高
    const longitudeRange = dv.range('longitude');
    const lantitudeRange = dv.range('lantitude');
    const ratio = (longitudeRange[1] - longitudeRange[0]) / (lantitudeRange[1] - lantitudeRange[0]);
    const maxSize = propsWidth || (this.root ? this.root.parentNode.clientWidth : 200);
    let width;
    let height;
    if (ratio > 1) {
      width = maxSize;
      height = width / ratio;
    } else {
      width = maxSize * ratio;
      height = maxSize;
    }
    // end: 计算地图的最佳宽高
    this.setState({
      width,
      height,
      name,
      dv,
    });
  };

  // 数据转换
  processData = geoJSON => {
    const mapData = {
      type: 'FeatureCollection',
      features: geoJSON,
    };
    // 构造数据
    const userData = [];
    if (geoJSON && geoJSON.length) {
      geoJSON.map(item => {
        const { name, adcode } = item.properties;
        userData.push({
          name,
          adcode,
          value: Math.round(Math.random() * 10000),
        });
      });
    }
    const ds = new DataSet();
    const geoDataView = ds.createView().source(mapData, {
      type: 'GeoJSON',
    }); // geoJSON 经纬度数据

    // 数据格式转换
    const dvData = ds.createView().source(userData);
    dvData.transform({
      type: 'geo.region',
      field: 'name',
      geoDataView,
      as: ['longitude', 'lantitude'],
    });
    return dvData;
  };

  getG2Instance = chart => {
    this.chart = chart;
  };

  render() {
    const { height, width, name, dv } = this.state;
    const {
      height: propsHeight,
      areaNumber,
      drillDown,
      textSize,
      textPosition,
      onMapClick,
    } = this.props;

    return (
      <div
        style={{ display: 'table', height: propsHeight, width: '100%' }}
        ref={e => (this.root = e)}
      >
        {drillDown && (
          <span
            style={{
              display: 'inline-block',
              fontSize: '0.4rem',
              color: '#fff',
              position: 'absolute',
              top: '1rem',
              left: '1rem',
              height: '0.8rem',
              lineHeight: '0.8rem',
              background: '#225e7a',
              boxShadow: '0 0.04rem 0 0 #033248',
              borderRadius: '0.2rem',
              padding: '0 0.2rem',
            }}
          >
            {name}
          </span>
        )}
        <div style={{ textAlign: 'center', display: 'table-cell', verticalAlign: 'middle' }}>
          <Chart
            key={areaNumber}
            height={height}
            width={width}
            data={dv}
            padding={0}
            onPlotClick={({ data }) => {
              if (data) {
                if (drillDown && data._origin && data._origin.adcode && onMapClick) {
                  onMapClick(data._origin.adcode, data._origin.name);
                } else if (onMapClick) {
                  onMapClick(areaNumber);
                }
              }
            }}
            onLabelClick={e => {
              const { data } = e;
              if (data && drillDown && data.appendInfo && data.appendInfo.adcode && onMapClick) {
                onMapClick(data.appendInfo.adcode, data.appendInfo.name, true);
              }
            }}
            onGuideTextClick={() => {
              if (onMapClick) onMapClick(areaNumber);
            }}
            style={{ display: 'inline-block', textAlign: 'center' }}
            onGetG2Instance={this.getG2Instance}
          >
            <Geom
              type="polygon"
              position="longitude*lantitude"
              select={{
                // 设置是否允许选中以及选中样式
                mode: 'single', // 多选还是单选
                cancelable: false, // 选中是否允许取消
                style: {
                  fill: '#1e415d', // 选中的样式
                  shadowBlur: 15 * window.viewportScale,
                  shadowColor: '#034a68',
                  shadowOffsetY: 10 * window.viewportScale,
                  stroke: '#fff',
                  lineWidth: 1,
                },
              }}
              style={{ cursor: 'pointer' }}
              color={['value', drillDown ? '#6dcaf3-#0D74A0-#07415A' : '#005b8a']}
            >
              {drillDown && (
                <Label
                  content="name"
                  offset={0}
                  textStyle={(_, { point }) => {
                    return {
                      fill: '#fff',
                      fontSize: 18 * window.viewportScale,
                      shadowBlur: 3 * window.viewportScale,
                      shadowColor: '#000',
                      cursor: 'pointer',
                      appendInfo: point,
                    };
                  }}
                />
              )}
            </Geom>
            {!drillDown && (
              <Guide>
                <Text
                  top
                  content={name}
                  position={textPosition || ['30%', '50%']}
                  style={{
                    fill: '#fff',
                    fontSize: (textSize || 18) * window.viewportScale,
                    shadowBlur: 3 * window.viewportScale,
                    shadowColor: '#000',
                    cursor: 'pointer',
                  }}
                />
              </Guide>
            )}
          </Chart>
        </div>
      </div>
    );
  }
}

const DrillDownMap = props => {
  const { areaNumber } = props;
  return (
    <Map useAMapUI>
      <UIMap {...props} key={areaNumber} />
    </Map>
  );
};

export default DrillDownMap;
